﻿#include "loginwidget.h"
#include "ui_loginwidget.h"
#include <QCryptographicHash>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QPainter>
#include <QPaintEvent>
#include <QStyle>
#include <QStyleOption>
#include <QTimer>
#include "clientcallback.h"
#include "confsettings.h"
#include "globaltools.h"
#include "httppost.h"
#include "litedb.h"
#include "loginsemaphore.h"
#include "servertimesync.h"
#include "uitools.h"
#include "usersettings.h"

LoginWidget::LoginWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::LoginWidget),
    placeHolderDisplayPW(10,style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter)),placeHolderInputPW(QObject::trECSUTF8("<请输入密码>"))
{
    ui->setupUi(this);
    auto globalConf = ConfSettings::instance();
    ui->label_title->setText(globalConf->getTitleLabel());
    if(globalConf->updaterName.isEmpty())
        ui->btn_check_update->hide();
    else
        connect(ui->btn_check_update, SIGNAL(clicked(bool)), parent, SLOT(slot_run_updater()));

    LoginSemaphore::instance()->cleanAll();
    ServerTimeSync::instance()->invalidate();
    ClientCallback::instance()->im_logout();
    LiteDb::instance()->close_user_db();
    ui->cbb_user_id->lineEdit()->setAlignment(Qt::AlignCenter);
    ui->cbb_user_id->lineEdit()->setPlaceholderText(QObject::trECSUTF8("[登录ID]"));
    ui->edit_password->setPlaceholderText(QObject::trECSUTF8("<请输入密码>"));
    if(parent)
    {
        connect(ui->button_min,SIGNAL(clicked(bool)),parent,SLOT(showMinimized()));
        connect(ui->button_close,SIGNAL(clicked(bool)),parent,SLOT(close()));
    }

    auto settings = UserSettings::instance();
    //是否记住密码
    bool save_password = settings->getBool(UserSettings::sys_save_password);
    if(save_password)
    {
        ui->ckb_save_password->setChecked(true);
    }

    //添加历史登录ID
    QStringList id_list = settings->getIDs();
    if(!id_list.empty())
    {
        foreach (const QString& id, id_list) {
            if(ui->cbb_user_id->findText(id)==-1)
                ui->cbb_user_id->addItem(id);
        }
    }
    //获取上次登录ID
    QString last_login = settings->getString(UserSettings::sys_last_login_id);
    if(!last_login.isEmpty())
    {
        int index=ui->cbb_user_id->findText(last_login);
        if(index>=0)
            ui->cbb_user_id->setCurrentIndex(index);
        else
            ui->cbb_user_id->setEditText(last_login);
    }

    //是否自动登陆
    static bool isfirst = true;
    bool auto_login = false;
    if(isfirst)
    {
        isfirst = false;
        auto_login = settings->getBool(UserSettings::sys_auto_login);
    }
    if(auto_login)
    {
        ui->ckb_auto_login->setChecked(true);
        //自动登录
        if(!last_login.isEmpty())
        {
            hashedPassword = settings->getHashedPW(last_login);
            if(!hashedPassword.isEmpty())
            {
                ui->edit_password->clear();
                QTimer::singleShot(100, ui->btnLogin, SLOT(click()));
            }
        }
    }
    else if(save_password)
    {
        QString user_id=ui->cbb_user_id->currentText().simplified();
        if(!user_id.isEmpty())
            slot_cbb_user_id_currentIndexChanged(user_id);
    }

    connect(ui->cbb_user_id,SIGNAL(currentIndexChanged(QString)),SLOT(slot_cbb_user_id_currentIndexChanged(QString)));
}

LoginWidget::~LoginWidget()
{
    delete ui;
}

QString LoginWidget::handle_login_ack(int result, QVariantHash &param)
{
    QString returnid;
    if(result == 0)
    {
        ui->btnCancelLogin->hide();
        ui->button_close->hide();
        ui->button_min->hide();
        ui->label_ing->setText(QObject::trECSUTF8("正在打开界面..."));
        repaint();

        if(qint64 uid = getParam(param, cmd_param_uid).toLongLong())
            LiteDb::instance()->init_user_db(QString::number(uid));

        auto settings = UserSettings::instance();
        bool auto_checked=ui->ckb_auto_login->isChecked();
        bool save_checked=ui->ckb_save_password->isChecked();

        bool login = !login_id.isEmpty();
        if(login)
        {
            if(save_checked)
            {
                QString pw = ui->edit_password->text();
                if(pw.isEmpty())
                    settings->setPW(login_id,hashedPassword);
                else
                    settings->setPW(login_id,pw);
            }
            else
                settings->setPW(login_id);
        }

        bool saveSetting = false;

        if(settings->getBool(UserSettings::sys_save_password)!=save_checked)
        {
            saveSetting = true;
            settings->setValue(UserSettings::sys_save_password,save_checked);
        }

        if(settings->getBool(UserSettings::sys_auto_login)!=auto_checked)
        {
            saveSetting = true;
            settings->setValue(UserSettings::sys_auto_login,auto_checked);
        }
        if(login && settings->getString(UserSettings::sys_last_login_id)!=login_id)
        {
            saveSetting = true;
            settings->setValue(UserSettings::sys_last_login_id,login_id);
        }

        if(saveSetting)
            settings->save_system_setting();

        returnid = login_id;
    }
    else
    {
        QString msg = ClientCallback::getErrorString(result);
        LoginSemaphore::instance()->cleanAll();
        information(QObject::trECSUTF8("登录失败"),msg+"!", this);
        ui->stackedWidget->setCurrentWidget(ui->loginpage);
    }
    login_id.clear();
    return returnid;
}

void LoginWidget::handle_login()
{
    ui->stackedWidget->setCurrentWidget(ui->cancelpage);
    repaint();

    const kkim_login_param& param = ClientCallback::instance()->get_login_param();

    if(!handle_login(param.account, param.hashed_password))
        ui->stackedWidget->setCurrentWidget(ui->loginpage);
}

bool LoginWidget::handle_login(const QString &account, const QByteArray &hashedPW)
{
    if(ConfSettings::instance()->validProxy.isEmpty())
    {
        //下载proxy
        postJson(QUrl(ConfSettings::instance()->validDomain+"/userApi/getSystemInfo"), QJsonDocument(QJsonObject({{"appname", QApplication::applicationName()}})).toJson(QJsonDocument::Compact), this, SLOT(slot_proxy_finished()));
        return true;
    }

    if(account.isEmpty() || hashedPW.isEmpty())
    {
        information(QObject::trECSUTF8("错误"), QObject::trECSUTF8("请正确输入用户ID和密码"), this);
        return false;
    }

    /*LiteDb::instance()->init_user_db(QString::number(account));*/
    if(!ClientCallback::instance()->im_login(account,hashedPW))
    {
        information(QObject::trECSUTF8("错误"), QObject::trECSUTF8("不能重复登录"), this);
        return false;
    }
    return true;
}

void LoginWidget::paintEvent(QPaintEvent *e)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    p.setClipRegion(e->region());
    p.setClipRect(e->rect());
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void LoginWidget::on_btnLogin_clicked()
{
    if(ConfSettings::instance()->validDomain.isEmpty())
    {
        information(QObject::trECSUTF8("错误"), QObject::trECSUTF8("服务器配置缺失"), this);
        return;
    }

    QString account = ui->cbb_user_id->currentText().simplified();
    QString pw = ui->edit_password->text();
    QByteArray hashed = pw.isEmpty() ? hashedPassword : QCryptographicHash::hash(pw.toUtf8(), QCryptographicHash::Md5);
    if(account.isEmpty() || hashed.isEmpty())
    {
        information(QObject::trECSUTF8("错误"), QObject::trECSUTF8("请正确输入用户ID和密码"), this);
        return;
    }

    ui->stackedWidget->setCurrentWidget(ui->cancelpage);
    repaint();

    login_id = account;
    if(handle_login(account, hashed))
        return;
    //发生错误
    login_id.clear();
    ui->stackedWidget->setCurrentWidget(ui->loginpage);
}

void LoginWidget::on_btnCancelLogin_clicked()
{
    ClientCallback::instance()->im_logout();
    ui->stackedWidget->setCurrentWidget(ui->loginpage);
    LoginSemaphore::instance()->cleanAll();
}

void LoginWidget::on_cbb_user_id_editTextChanged(const QString &)
{
    if(!hashedPassword.isEmpty())
    {
        hashedPassword.clear();
        ui->edit_password->setPlaceholderText(placeHolderInputPW);
    }
}

void LoginWidget::on_btn_clear_clicked()
{
    if(confirm(QObject::trECSUTF8("清除密码"),QObject::trECSUTF8("是否确认清除所有密码?"),this))
    {
        UserSettings::instance()->clearIDPW();
        ui->cbb_user_id->clear();
    }
}

void LoginWidget::slot_cbb_user_id_currentIndexChanged(const QString &arg1)
{
    QString id = arg1.simplified();
    if(UserSettings::instance()->getBool(UserSettings::sys_save_password))
    {
        hashedPassword = UserSettings::instance()->getHashedPW(id);
        if(!hashedPassword.isEmpty())
            ui->edit_password->setPlaceholderText(placeHolderDisplayPW);
        else
            ui->edit_password->setPlaceholderText(placeHolderInputPW);
    }
}

void LoginWidget::slot_proxy_finished()
{
    auto reply = qobject_cast<QNetworkReply*>(sender());
    if(reply && reply->error() == QNetworkReply::NoError)
    {
        QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
        if(doc.isObject())
        {
            auto root = doc.object();
            if(root.value("success").toBool())
            {
                QString proxy = root.value("obj").toObject().value("ProxyServer").toString();
                if(!proxy.isEmpty())
                {
                    if(auto settings = UserSettings::instance())
                    {
                        if(settings->setValueIfChanged(UserSettings::sys_server_proxy, proxy))
                        {
                            settings->save_system_setting();
                            auto conf = ConfSettings::instance();
                            conf->updateProxy(conf->validDomain, proxy);
                            ClientCallback::instance()->set_pxy_servers(conf->validProxy);
                        }
                    }
                    else
                        ClientCallback::instance()->set_pxy_servers(proxy);
                    if(!login_id.isEmpty() && ui->stackedWidget->currentWidget() == ui->cancelpage)
                    {
                        QString account = ui->cbb_user_id->currentText().simplified();
                        QString pw = ui->edit_password->text();
                        QByteArray hashed = pw.isEmpty() ? hashedPassword : QCryptographicHash::hash(pw.toUtf8(), QCryptographicHash::Md5);
                        if(handle_login(account, hashed))
                            return;
                        //发生错误
                        login_id.clear();
                        ui->stackedWidget->setCurrentWidget(ui->loginpage);
                    }
                    return;
                }
            }
        }
    }
    //失败
    information(QObject::trECSUTF8("登录失败"),QObject::trECSUTF8("获取登录服务器失败")+"!", this);
    ui->stackedWidget->setCurrentWidget(ui->loginpage);
    login_id.clear();
}
